import _ from 'lodash'
import { useCookies } from 'vue3-cookies'
import { store } from '@/store'
import { LoginRequest } from '@/services/login'
import { deep, defaultRouter, getResRouter } from '@/router/permissionTools'
import { LOGIN_METHOD_MAP } from '@/global-config/const'
import * as AccountTypes from '@/store/modules/Account/types'
import * as Types from '@/store/types'
import { ImageManage } from '@/services/uploadImg'

const { cookies } = useCookies()

/**
 * 加载对应组件
 * @param {String} name 对应模块名字
 * @param {String} view 对应组件页面名字
 */
export const loadComponent = (name?: string, view?:string) => {
  const modules = import.meta.glob('../**/*.vue')
  return modules[`../views/${name ? `${name}/${view}` : `${view}`}.vue`]
}

/**
 * 防抖
 * @param func {AnyFunction}
 * @param delay {number} 间隔时间，毫秒
 * @param immediate {boolean} 是否首次立即执行，默认false
 * @returns {AnyFunction}
 */
/* eslint-disable */
export const debounce = (func: (...args: any[]) => any, delay: number, immediate = false): AnyFunction => {
  let timeoutId: any

  function debounced(this: any, ...params: any[]): void {
    if (immediate) {
      func.apply(this, params)
      immediate = false
      return
    }
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => {
      func.apply(this, params)
    }, delay)
  }

  return debounced
}

/**
 * 节流函数 throttle
 * @param func 
 * @param delay 
 * @returns {AnyFunction}
 */
 export const throttle = (func: (...args: any[]) => any, delay: number = 300): AnyFunction => {  // 默认300毫秒
  let flag = true
  function throttled (this: any, ...params: any[]):void {
    if (flag) {
      func.apply(this, params)
      flag = false
    }
    const timer = setTimeout(() => {
      clearTimeout(timer)
      flag = true
    }, delay)
  }
  return throttled
}

/**
 * 登录后获取默认跳转的路由,参考车队项目
 * @param resources {Array}
 * @returns {string}
 */
export function getInitPath(resources: Array<Record<string, any>>) {
  const prefixPath = _.get(resources, '[0].children[0].router')
  let suffixPath = _.get(resources, '[0].children[0].children[0].router')
  suffixPath = suffixPath ? `/${suffixPath}` : ''
  return `/${prefixPath}${suffixPath}`
}

// 解析并处理左侧路由
export const getAllMenuList = (arr: Array<any>): Record<string, any> => {
  const inner = (iarr: any, r: string = ''): void => {
    iarr.forEach((item: Record<string, any>) => {
      // 微前端路由为兼容vue2项目，做了扁平化路由，vue3项目需要单独进行扁平化
      r = r.replace(/\/car-team\/system-qiankun\/departmentManage-qiankun/g, '/car-team/system-qiankun')
      item.router = `${r}/${item?.router}`
      if (item?.children?.length) {
        inner(item.children, item.router)
      }
    })
  }
  inner(arr)
  return arr
}

/**
 * 压缩图片通用方法
 * @param file 当前文件
 * @param beforeFn 前置处理函数 如果没有，请传null
 * @param compressOption 压缩配置选项
 * @returns 
 */
 export async function commonImageCompress(file:any, beforeFn?:Function, compressOption?:any ) {
  return new Promise((resolve, reject) => {
    const URL = window.URL || window.webkitURL
    // 这里需要计算出图片的长宽
    const img = new Image()
    img.onload = async () => {
      const isStop = !beforeFn ? false : beforeFn(img, resolve, reject)
      if (isStop) {
        return
      }
      if (!compressOption) {
        // 配置压缩选项 大小200kb, 比例缩小为原来的0.9
        const { width, height } = img
        compressOption = {
          size: 200,
          accuracy: 0.5,
          // type: "image/jpeg",
          width: Math.floor(width * 0.8),
          height: Math.floor(height * 0.8),
        }
      }
      // 开始进行压缩这里可以直接按kb来压缩
      try {
        const compressResult = await imageConversion.compressAccurately(file, compressOption)
        resolve(compressResult)
      } catch (e) {
        console.log('压缩错误：', e)
        ElMessage.error('图片压缩错误!')
        reject(file)
      }
    }
    // 需要把图片赋值
    let binaryData = [];
    binaryData.push(file);
    img.src = URL.createObjectURL(new Blob(binaryData))
  })
}

/**
 * 图片临时预览的地址
 * @param fileCode 文件code
 * @returns
 */
 export async function imageTempPreviewUrl(fileCode:string)  {
  // 1. 先获取临时授权
  const result = await ImageManage.getTemAccKey({fileCode})
  const tokenCode = result.code
  const { accKey } = result.data
  if (tokenCode !== 200) {
    return ''
  }
  // 2. 再获取文件预览地址
  return ImageManage.imageView({ fileCode, accKey })
}

/**
 * 同步设置cookie的值
 * @param key 键
 * @param value 值
 */
export function setCookie(
  key:string,
  value:string,
  expireTime?:string | undefined,
  path?:string | undefined,
  domain?:string | undefined,
  secure?:boolean | undefined,
  sameSite?:string | undefined) {
  cookies.set(key, value, expireTime, path, domain, secure, sameSite) // 保持当前会话
}

/**
 * 同步移除cookie的值
 * @param key 键
 * @param path 值
 * @param domain 域名
 */
export function removeCookie(
  key:string,
  path?:string | undefined,
  domain?:string | undefined) {
  cookies.remove(key, path, domain)
}

/**
 * 获取cookie
 * @param key 键
 */
export function getCookie(key:string) {
  return cookies.get(key)
}

/**
 * 设置用户中心，用户token的值
 * @param val 值
 */
export function setUcTokenAsCookie(val?:string) {
  // 检测当前是否存在cookie
  const ucToken = getCookie('uc_token')
  if (ucToken) return
  // 当前无cookie时
  if (!val) {
    // 读取本地vuex accessToken
    const { account: { accessToken } } = store.state as Record<string, any>
    const storeToken = accessToken
    // 没有vuex accessToken 则停止
    if (!storeToken) return
    // 有则赋值
    val = storeToken
  }
  setCookie('uc_token', val)
}

/**
 * 清理用户中心token的cookie信息
 */
export function clearUcTokenByCookie() {
  cookies.remove('uc_token')
}

/**
 * 获取权限路由，后续需要优化，从接口中获取所有的，不进行qiankunRouters的读取
 * @param menuList 菜单列表
 * @returns 
 */
export const getPermissionsRoutersMap = (menuList: any) => {
  const permissionsRouters = deep(menuList).concat(defaultRouter)
  return getResRouter(permissionsRouters)
}

// 获取菜单时当前是否是黑名单，如果需要突破黑名单需要额外添加参数
function inMenuBlackList () {
  let flag = false
  const copyRouter = defaultRouter.filter(item => item !== '/')
  copyRouter.some((item) => {
    if (window.location.hash.includes(item)) {
      flag = true
      return true
    }
  })
  return flag
}

/**
 * 首页router的重定向逻辑
 */
const redirectToDefault = (router: any, menuList: Record<string, any>) => {
  try {
    const routerChildren: Record<string, any> = menuList[0] ? (menuList[0] as any)?.children : []
    const indexRoute = router.getRoutes().filter((r: Record<string, any>) => r.path === '/')[0]
    indexRoute.redirect = (routerChildren && routerChildren.length) ? routerChildren[0]?.router : '/login'
  } catch (e) {
    console.log(e)
  }
}
/**
 * 获取左侧菜单
 * @param compulsion 强制更新左侧menuList，默认为否
 */
 export const getMenuList = async (compulsion: boolean = false, router: any) => {
  const isBlack = inMenuBlackList()
  if (isBlack && !compulsion) return
  try {
    const { code, data: { resources, departmentId, roleId } } = await LoginRequest.getResourceTree({
      departmentId: null,
      roleId: null
    })
    const copyResources:any[] = JSON.parse(JSON.stringify(resources))
    if (code !== 200) {
      return Promise.reject(false)
    }
    const menuList = getAllMenuList(copyResources[0]?.children || [])
    redirectToDefault(router, menuList)
    store.commit(`${AccountTypes.MODULE_NAME}/${AccountTypes.SET_ACCOUNT_DATA}`, {
      departmentId,
      roleId
    })
    store.commit(`${Types.GLOBAL_DATA}`, {
      menuList,
      permissionsRoutersMap: getPermissionsRoutersMap(menuList)
    })
    return Promise.resolve(resources)
  } catch (e) {
    return Promise.reject(false)
  }
}

/**
 * 通用的校验程序
 * @param {*} form 表单
 * @param {*} certainField 表单
 */
 export function commonValidate(form: any, certainField?:any) {
  return new Promise(async (resolve) => {
    const attr = certainField ? 'validateField' : 'validate'
    if (!certainField) {
      form[attr]((valid: boolean) => {
        resolve(valid)
      })
      return
    }
    form[attr](certainField, (valid: boolean) => {
      resolve(valid)
    })
  })
}

/**
 * 重置表单项
 * @param form 当前表单对象
 * @param callback 回调
 */
 export function resetFormField(form: any, callback?: Function) {
  form?.resetFields() // 重置所有表单项
  callback && callback() // 执行其他回调
}

/**
 * 通用的获取用户数据的展示信息
 * @param {*} user 用户数据
 * @returns
 */
 export function commonAccountShowText(user:any) {
  const { loginMethod, account, phone, email } = user
  let text = ''
  switch(loginMethod) {
    case LOGIN_METHOD_MAP.phone:
      text = phone;
      break;
    case LOGIN_METHOD_MAP.email:
      text = email
      break;
    case LOGIN_METHOD_MAP.account:
      text = account
      break;
    default:
  }
  return text
}
